package middlewares

import (
	"github.com/gin-gonic/gin"
	"go_frame/models"
	"go_frame/pkg/jwt"
	"strings"
	"go_frame/controllers"
)

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware(option ...models.JWTAuthMiddlewareOptions) func(c *gin.Context) {
	var opt models.JWTAuthMiddlewareOptions
	if len(option) > 0 {
		opt = option[0]
	} else {
		opt.Type = "header"
	}
	return func(c *gin.Context) {
		// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
		// 这里假设Token放在Header的Authorization中，并使用Bearer开头
		// 这里的具体实现方式要依据你的实际业务情况决定
		var tokenStr string
		// 第一种，放在请求头
		if opt.Type == "header" {
			authHeader := c.Request.Header.Get("Authorization")
			if authHeader == "" {
				controllers.ResponseError(c, controllers.CodeNeedLogin)
				c.Abort()
				return
			}
			// 按空格分割
			parts := strings.SplitN(authHeader, " ", 2)
			if !(len(parts) == 2 && parts[0] == "Bearer") {
				controllers.ResponseError(c, controllers.CodeInvalidToken)
				c.Abort()
				return
			}
			tokenStr = parts[1]
			// 第二种，放在 query 请求参数中
		} else if opt.Type == "query" {
			queryToken := c.Query("token")
			if queryToken != "" {
				tokenStr = queryToken
			}
		}
		// parts[1]是获取到的tokenString，我们使用之前定义好的解析JWT的函数来解析它
		mc, err := jwt.ParseToken(tokenStr)
		if err != nil {
			controllers.ResponseError(c, controllers.CodeInvalidToken)
			c.Abort()
			return
		}
		// 将当前请求的userid信息保存到请求的上下文c上
		c.Set(controllers.CtxUserIdKey, mc.UserID)
		c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
	}
}
